package dk.lector.service;


import java.util.Calendar;
import java.util.Date;

import dk.lector.R;
import dk.lector.datasource.ConfigDBRepository;
import dk.lector.datasource.DBhelper;
import dk.lector.domain.TeamShareMobile;
import dk.lector.exception.ExceptionHandler;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;

public class CleanupServiceHelper extends BroadcastReceiver {

	private static final String TAG = CleanupServiceHelper.class.getSimpleName();
	private static final String BOOT = "android.intent.action.BOOT_COMPLETED"; 
	private static final String CACHE_FILENAME = "ServiceHelperCache";
	
	public static final String CLEANUP_CACHE_TABLE = "cleanup_cache";
	public static final String TIMESTAMP_ROW = "timestamp";
	public static final String USER_ALARM_ROW = "user_alarm";
	public static final String DOC_ALARM_ROW = "doc_alarm";

	private static int DEFAULT = 0;
	private static int DOCS = 1;
	private static int USER = 2;

	public static final String EXTRA_INTERVAL_KEY = "defined_interval";
	public static int minutesToKeepDocuments, minutesToKeepUser;
	//TODO Very short interval only meant for testing.
	private static final long DEFAULT_ALARM_INTERVAL = 1;
	public static final int DEFINED_ALARM_DEFAULT_INTERVAL = 30;
	public static final String EXTRA_TARGET_KEY = "target";
	public static final String EXTRA_TARGET_USER = "user";
	public static final String EXTRA_TARGET_DOCS = "docs";
	
	

	 public void onReceive(Context context, Intent intent) {
		 TeamShareMobile core = (TeamShareMobile)context.getApplicationContext();
		 try {
			Thread.sleep(30000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		 Log.d(TAG, "CleanupServiceHelper has received: " + intent.getAction());
		 if(intent.getAction().equals(context.getString(R.string.ACTION_DEFINED_ALARM)))
		 {
			 startService(context, intent);
			 return;
		 }
		 else if(intent.getAction().equals(BOOT))
		 {
			if(getLastCachedSettings(context).length == 0){
				Log.d(TAG, "Setting up default alarm wit interval: " + DEFAULT_ALARM_INTERVAL);
				setDefault(context);
			}
			return;
		 }
		 else if(intent.getAction().equals(context.getString(R.string.ACTION_DEFAULT_ALARM)))
		 {
			 if(core.hasConfig()){
				 Log.d(TAG, "Default alarm received, attempting to setup service");
				 setupService(core);
			 }
			 return;
		 }
		 else if(intent.getAction().equals(context.getString(R.string.ACTION_CONFIG_DOWNLOADED)))
		 {
			 Log.d(TAG, "Config downloaded, attempting to setup service");
			 setupService(core);
			 return;
		 }
		 
		 else Log.d(TAG, "Intent received, but not reconised");
	  }
	 
	

	private static PendingIntent getDefaultIntent(Context context)
	 {
	
			Intent defaultAlarm = new Intent(context, CleanupServiceHelper.class).setAction(context.getString(R.string.ACTION_DEFAULT_ALARM));
			PendingIntent pendingDefaultAlarm = PendingIntent.getService(context, DEFAULT, defaultAlarm, PendingIntent.FLAG_UPDATE_CURRENT);
			return pendingDefaultAlarm;	 
	 }
	 
	 private static void setDefault(Context context)
	 {
		Date now = Calendar.getInstance().getTime();
		AlarmManager am = (AlarmManager)context.getSystemService(context.ALARM_SERVICE);
		PendingIntent pi = getDefaultIntent(context);
		am.cancel(pi);
		am.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, now.getTime() + DEFAULT_ALARM_INTERVAL, DEFAULT_ALARM_INTERVAL, pi);
	}
	 
	 private static void startService(Context context,Intent intent)
	 {
		 intent.setClass(context, CleanupService.class);
		 intent.setAction(context.getString(R.string.ACTION_START_CLEANUP_SERVICE));
	
		 context.startService(intent);		 
	 }
	 
	public static void setupService(TeamShareMobile core)
	{
		AlarmManager am = (AlarmManager)core.getSystemService(core.ALARM_SERVICE);
		am.cancel(getDefaultIntent(core));
		
		if(core.hasConfig())
		{	
			try
			{	
				minutesToKeepDocuments = Integer.parseInt(ConfigDBRepository.getValue(core, "TimeToKeepDocs"));
				minutesToKeepUser = Integer.parseInt(ConfigDBRepository.getValue(core, "TimeToKeepUser"));	
			}
	
			catch (Exception e)
			{
				minutesToKeepDocuments = minutesToKeepUser = DEFINED_ALARM_DEFAULT_INTERVAL;
				e.printStackTrace();
			}
		}
		else
		{
			setDefault(core);
			return;
		}	

		Intent userAlarm = new Intent(core, CleanupServiceHelper.class ).setAction(core.getString(R.string.ACTION_DEFINED_ALARM));
		Intent docAlarm = new Intent(core, CleanupServiceHelper.class).setAction(core.getString(R.string.ACTION_DEFINED_ALARM));;	
		userAlarm.putExtra(EXTRA_TARGET_KEY, EXTRA_TARGET_USER);
		docAlarm.putExtra(EXTRA_TARGET_KEY, EXTRA_TARGET_DOCS);
		PendingIntent pUserAlarm = null;
		PendingIntent pDocAlarm = null;
		
		int[] lastRunCachedSettings = getLastCachedSettings(core);
		
		if(lastRunCachedSettings.length != 0)
		{
			Log.d(TAG, "Removing old alarms!");
			userAlarm.putExtra(EXTRA_INTERVAL_KEY, lastRunCachedSettings[0]);
			docAlarm.putExtra(EXTRA_INTERVAL_KEY, lastRunCachedSettings[1]);
		
			pUserAlarm = PendingIntent.getService(core, USER, userAlarm, PendingIntent.FLAG_UPDATE_CURRENT);
			pDocAlarm = PendingIntent.getService(core, DOCS, docAlarm, PendingIntent.FLAG_UPDATE_CURRENT);
			am.cancel(pUserAlarm);
			am.cancel(pDocAlarm);
		}
		
		long now = Calendar.getInstance().getTimeInMillis();
		int scheduled = 0;
		
		if(minutesToKeepDocuments != 0){
			long docInterval = minutesToKeepDocuments*60000/2;
			docAlarm.putExtra(EXTRA_INTERVAL_KEY, minutesToKeepDocuments);
			pDocAlarm = PendingIntent.getService(core, DOCS, docAlarm, PendingIntent.FLAG_UPDATE_CURRENT);
			am.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, now + docInterval ,docInterval, pDocAlarm);
			scheduled++;
		}
		
		if(minutesToKeepUser != 0){
			long userInterval = minutesToKeepUser*60000/2;
			userAlarm.putExtra(EXTRA_INTERVAL_KEY, minutesToKeepUser);
			pUserAlarm = PendingIntent.getService(core, USER, userAlarm, PendingIntent.FLAG_UPDATE_CURRENT);		
			am.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, now + userInterval ,userInterval, pUserAlarm); 
			scheduled++;
		}	
		if(scheduled==0){setDefault(core);return;};
		
		cacheCurrentSettings(core,minutesToKeepUser,minutesToKeepDocuments);
		Log.d(TAG, "Defined alarm(s) has been set!");
	} 

	public static void cacheCurrentSettings(Context context, int userInterval, int docInterval)
	{
		Log.d(TAG, "Cacheing alarm settings");
		
		DBhelper dbh = new DBhelper(context);
		SQLiteDatabase db = dbh.getWritableDatabase();
		long now = Calendar.getInstance().getTimeInMillis();
		
	//TODO	db.isDbLockedByOtherThreads(), the db wrapper is actually a singleton, so concurrency should be alright
		
		ContentValues values = new ContentValues();
		values.put(TIMESTAMP_ROW, now);
		values.put(USER_ALARM_ROW, userInterval);
		values.put(DOC_ALARM_ROW, docInterval);
		db.insert(CLEANUP_CACHE_TABLE, null, values);
		db.close();
		
	}
 
	// TODO forgot to use the timestamp... Leaving it for the time being.
	public static int[] getLastCachedSettings(Context context)
	{
		Log.d(TAG, "loading alarm settings");
		int[] res = new int[2];
		
		DBhelper dbh = new DBhelper(context);
		SQLiteDatabase db = dbh.getWritableDatabase();
		Cursor c = db.query(CLEANUP_CACHE_TABLE, new String[]{USER_ALARM_ROW, DOC_ALARM_ROW}, null, null, null, null, null);
		
		try {
			if(c.getCount() != 0 && !c.equals(null))
			{
				if(!c.moveToLast())throw new Exception("Empty cursor returned!");
				
				res[0] = c.getInt(c.getColumnIndex(USER_ALARM_ROW));
				res[1] = c.getInt(c.getColumnIndex(DOC_ALARM_ROW));
				db.delete(CLEANUP_CACHE_TABLE, null, null);
				db.close();
				return res;	
			}
			else res = new int[0];
		} 
		catch (Exception e) 
		{
			res = new int[0];
			e.printStackTrace();
		}
		finally{db.close();}
		
		return res;
	}
	
}
